package com.mxpio.erp.inventory.policy.impl;

import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.NoticeStatusEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.inventory.entity.*;
import com.mxpio.erp.common.jpa.entity.BizNoticeType;
import com.mxpio.erp.common.order.policy.AbstractNoticePolicy;
import com.mxpio.erp.common.order.policy.NoticeContext;
import com.mxpio.erp.common.quality.entity.InQualityOrder;
import com.mxpio.erp.common.quality.entity.InQualityOrderLine;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.common.workshop.entity.MoPickingNotice;
import com.mxpio.erp.common.workshop.entity.MoPickingNoticeLine;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.impl.CrudType;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 送货计划 通知单执行策略
 * @author mxpio
 *
 */
public class FeedPlanNoticePolicy extends AbstractNoticePolicy {

	private List<OrderExcuteLineVo> orderExcuteVos;

	public FeedPlanNoticePolicy(List<OrderExcuteLineVo> orderExcuteVos) {
		this.orderExcuteVos = orderExcuteVos;
	}
	
	@Override
	public void execute(NoticeContext context) {
		
	}

	@Override
	public void apply(NoticeContext context) {
		if(beforeExecute(context)) {
			execute(context);
			FeedPlanNotice feedPlanNotice = (FeedPlanNotice) context.getEntity();
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();
			//送货计划单拆单，明细均为单条数据
			String inQualityControl = orderExcuteVos.get(0).getInQualityControl();
			if (StringUtils.equals(inQualityControl, CommonEnums.YesNo.YES.getCode())){//需要生成验收单
				InQualityOrder notice = new InQualityOrder();
				notice.setFeedPlanNoticeNo(feedPlanNotice.getNoticeNo());//
				notice.setNoticeDate(new Date());
				notice.setWhCode(feedPlanNotice.getWhCode());
				notice.setAccessType(feedPlanNotice.getAccessType());
				notice.setPickingType(NoticeStatusEnums.NoticeType.FP_IN.getCode());
				notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());
				notice.setBizOrderNo(feedPlanNotice.getNoticeNo());
				JpaUtil.save(notice);
				feedPlanNotice.setInQualityNoticeNo(notice.getNoticeNo());//记录验收通知单号

				OrderExcuteLineVo vo = orderExcuteVos.get(0);
				InQualityOrderLine noticeLine = new InQualityOrderLine();
				noticeLine.setItemCode(vo.getItemCode());
				noticeLine.setNoticeNo(notice.getNoticeNo());
				noticeLine.setQuantity(vo.getQuantity());
				noticeLine.setSort(vo.getSort());
				noticeLine.setLotNo(vo.getLotNo());
				noticeLine.setSubLotIndex(vo.getSubLotIndex());
				noticeLine.setLineNo("1");
				Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
				noticeLine.setItemName(item.getItemName());
				noticeLine.setItemSpec(item.getItemSpec());
				noticeLine.setUnitCode(item.getUnitCode());
				noticeLine.setDrawingNo(item.getDrawingNo());
				noticeLine.setOriginBizNo(feedPlanNotice.getNoticeNo());
				noticeLine.setOriginBizLineNo(vo.getNoticeLineNo());
				JpaUtil.save(noticeLine);
			}else{//不需要生成验收单
				/*
					送货计划通知单确认：
					1.生成对应入库仓单及明细，且自动执行入库，生产流水。
					2.确认对应的领(补)料通知单，且生成对应的出库仓单，且仓单自动执行。执行的明细和入对应(批次)
				*/
				WarehouseOrder inWo = null;
				int lineNo = 0;
				List<BizNoticeType> bizNoticeTypes = JpaUtil.linq(BizNoticeType.class).list();
				Map<String, BizNoticeType> typesMap = JpaUtil.index(bizNoticeTypes);

				Set<String> itemCodeSet = orderExcuteVos.stream().map(OrderExcuteLineVo::getItemCode).collect(Collectors.toSet());
				List<Item> itemList = JpaUtil.linq(Item.class).in("itemCode", itemCodeSet).list();
				Map<Object, Item> itemMap = JpaUtil.index(itemList, "itemCode");


				List<WarehouseOrderLine> inWoLines = new ArrayList<>();
				boolean automatic = false;//自动化执行标志
				if (automatic){//自动入和自动出
					for(OrderExcuteLineVo vo : orderExcuteVos){
						lineNo++;
						if(inWo == null){
							inWo = new WarehouseOrder();
							inWo.setAccessType(feedPlanNotice.getAccessType());
							inWo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
							inWo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
							inWo.setOrderStatus(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode());
							inWo.setOrderDate(new Date());
							inWo.setOriginBizNo(feedPlanNotice.getNoticeNo());//取送货计划的单号
							inWo.setWhCode(feedPlanNotice.getWhCode());//取送货计划的仓库
							inWo.setWoType(feedPlanNotice.getPickingType());
							inWo.setOriginNoticeNo(feedPlanNotice.getNoticeNo());//关联noticeno字段
							inWo.setExecuteTime(new Date());
							inWo.setExecutor("8888");//自动化助手，默认指定用户
							JpaUtil.save(inWo);
						}
						WarehouseOrderLine line = new WarehouseOrderLine();
						line.setWhCode(inWo.getWhCode());
						line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
						line.setItemCode(vo.getItemCode());
						Item item = itemMap.get(vo.getItemCode());
						if (item!=null){
							line.setItemGroupCode(item.getItemGroupCode());
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
						}
						line.setQuantity(vo.getQuantity());
						line.setBizNo(inWo.getBizNo());
						line.setLineNo(lineNo+"");
						line.setOriginBizNo(feedPlanNotice.getNoticeNo());//取送货计划的单号
						line.setOriginBizLineNo(vo.getNoticeLineNo());//取送货计划的行号
						line.setSort(vo.getSort());
						//通知单执行，均为入的情况
						if(context.getLotService() == null){
							line.setLotNo("none");
							line.setSubLotIndex("0");
						}else{
							Lot newLot = context.getLotService().getNewLot(feedPlanNotice, vo, typesMap);
							if (newLot!=null){
								line.setLotNo(newLot.getLotNo());
								line.setSubLotIndex(newLot.getSubLotIndex());
							}else{
								line.setLotNo("none");
								line.setSubLotIndex("0");
							}
						}
						line.setOriginNoticeNo(feedPlanNotice.getNoticeNo());
						line.setOriginNoticeLineNo(vo.getNoticeLineNo());
						JpaUtil.save(line);
						inWoLines.add(line);

						//自动执行，生成流水
						InvFlow inFlow = new InvFlow();
						inFlow.setAccessType(inWo.getAccessType());
						inFlow.setItemCode(line.getItemCode());
						inFlow.setWhCode(inWo.getWhCode());
						inFlow.setQuantity(line.getQuantity());
						inFlow.setMemo(inWo.getMemo());
						inFlow.setOriginBizNo(inWo.getOriginBizNo());
						inFlow.setOriginBizType(inWo.getOriginBizType());
						inFlow.setOriginBizLineNo(line.getOriginBizLineNo());
						inFlow.setWoBizNo(inWo.getBizNo());
						inFlow.setWoBizType(inWo.getWoType());
						inFlow.setWoBizLineNo(line.getLineNo());
						inFlow.setLotNo(line.getLotNo());
						inFlow.setSubLotIndex(line.getSubLotIndex());//增加子批索引
						JpaUtil.save(inFlow);
					}
					//确认对应的领(补)料通知单，且生成对应的出库仓单，且仓单自动执行。执行的明细和入对应(批次)
					String sourcePickingNoticeNo = feedPlanNotice.getSourcePickingNoticeNo();//源领/补料通知单
					MoPickingNotice pickingNotice = JpaUtil.linq(MoPickingNotice.class).collect("noticeNo", MoPickingNoticeLine.class, "noticeNo").equal("noticeNo", sourcePickingNoticeNo).findOne();
					pickingNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());//确认状态
					pickingNotice.setSaveTransient(true);//保存子表
					List<MoPickingNoticeLine> moPickingNoticeLines = pickingNotice.getMoPickingNoticeLines();
					Map<String, MoPickingNoticeLine> pickingNoticeLineMap = JpaUtil.index(moPickingNoticeLines, "lineNo");
					List<FeedPlanNoticeLine> feedPlanNoticeLines = JpaUtil.linq(FeedPlanNoticeLine.class).equal("noticeNo", feedPlanNotice.getNoticeNo()).list();
					Map<String, FeedPlanNoticeLine> feedPlanNoticeLineMap = JpaUtil.index(feedPlanNoticeLines, "sourcePickingNoticeLineNo");

					Map<Object, WarehouseOrderLine> warehouseOrderLineMap = JpaUtil.index(inWoLines, "originNoticeLineNo");

					List<OrderExcuteLineVo> woVos = new ArrayList<>();
					for (String mpLineNo:pickingNoticeLineMap.keySet()){
						MoPickingNoticeLine moPickingNoticeLine = pickingNoticeLineMap.get(mpLineNo);
						FeedPlanNoticeLine feedPlanNoticeLine = feedPlanNoticeLineMap.get(mpLineNo);
						WarehouseOrderLine warehouseOrderLine = warehouseOrderLineMap.get(feedPlanNoticeLine.getLineNo());
						moPickingNoticeLine.setQuantity(warehouseOrderLine.getQuantity());//确认数量
						moPickingNoticeLine.setLotNo(warehouseOrderLine.getLotNo());
						moPickingNoticeLine.setSubLotIndex(warehouseOrderLine.getSubLotIndex());
						moPickingNoticeLine.setCrudType(CrudType.UPDATE);

						OrderExcuteLineVo excuteLineVo = new OrderExcuteLineVo();
						excuteLineVo.setBizOrderNo(moPickingNoticeLine.getOriginBizNo());
						excuteLineVo.setBizOrderlineNo(moPickingNoticeLine.getOriginBizLineNo());
						excuteLineVo.setItemCode(moPickingNoticeLine.getItemCode());
						excuteLineVo.setLineQuantity(moPickingNoticeLine.getQuantity());
						excuteLineVo.setLotNo(moPickingNoticeLine.getLotNo());
						excuteLineVo.setSubLotIndex(moPickingNoticeLine.getSubLotIndex());
						excuteLineVo.setQuantity(moPickingNoticeLine.getQuantity());
						excuteLineVo.setWhCode(pickingNotice.getWhCode());
						excuteLineVo.setMemo(moPickingNoticeLine.getMemo());
						excuteLineVo.setNoticeNo(pickingNotice.getNoticeNo());
						excuteLineVo.setNoticeLineNo(moPickingNoticeLine.getLineNo());
						woVos.add(excuteLineVo);
					}
					JpaUtil.save(pickingNotice);//保存 领料通知，主从数据

					//自动出生成仓单
					WarehouseOrder outWo = null;
					int woLineNo = 0;
					for(OrderExcuteLineVo vo : woVos){
						woLineNo++;
						if(outWo == null){
							outWo = new WarehouseOrder();
							outWo.setAccessType(pickingNotice.getAccessType());
							outWo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
							outWo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
							outWo.setOrderStatus(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode());
							outWo.setOrderDate(new Date());
							outWo.setOriginBizNo(vo.getBizOrderNo());
							outWo.setWhCode(vo.getWhCode());
							outWo.setWoType(pickingNotice.getPickingType());
							outWo.setOriginNoticeNo(pickingNotice.getNoticeNo());//关联noticeno字段
							outWo.setExecuteTime(new Date());
							outWo.setExecutor("8888");//自动化助手，默认指定用户
							JpaUtil.save(outWo);
						}
						WarehouseOrderLine line = new WarehouseOrderLine();
						line.setWhCode(outWo.getWhCode());
						line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
						Item item = itemMap.get(vo.getItemCode());
						line.setItemCode(vo.getItemCode());
						if (item!=null){
							line.setItemGroupCode(item.getItemGroupCode());
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
						}
						line.setQuantity(vo.getQuantity());
						line.setBizNo(outWo.getBizNo());
						line.setLineNo(woLineNo+"");
						line.setOriginBizNo(vo.getBizOrderNo());
						line.setOriginBizLineNo(vo.getBizOrderlineNo());
						line.setSort(woLineNo+"");
						line.setLotNo(vo.getLotNo());
						line.setSubLotIndex(vo.getSubLotIndex());
						line.setOriginNoticeNo(vo.getNoticeNo());
						line.setOriginNoticeLineNo(vo.getNoticeLineNo());
						JpaUtil.save(line);

						//自动执行，生成出流水
						InvFlow outFlow = new InvFlow();
						outFlow.setAccessType(outWo.getAccessType());
						outFlow.setItemCode(line.getItemCode());
						outFlow.setWhCode(outWo.getWhCode());
						outFlow.setQuantity(line.getQuantity());
						outFlow.setMemo(outWo.getMemo());
						outFlow.setOriginBizNo(outWo.getOriginBizNo());
						outFlow.setOriginBizType(outWo.getOriginBizType());
						outFlow.setOriginBizLineNo(line.getOriginBizLineNo());
						outFlow.setWoBizNo(outWo.getBizNo());
						outFlow.setWoBizType(outWo.getWoType());
						outFlow.setWoBizLineNo(line.getLineNo());
						outFlow.setLotNo(line.getLotNo());
						outFlow.setSubLotIndex(line.getSubLotIndex());//增加子批索引
						JpaUtil.save(outFlow);
					}
				}else{//入需要人工确认
					//生成未执行的入库仓单
					for(OrderExcuteLineVo vo : orderExcuteVos){
						lineNo++;
						if(inWo == null){
							inWo = new WarehouseOrder();
							inWo.setAccessType(feedPlanNotice.getAccessType());
							inWo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
							inWo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
							inWo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
							inWo.setOrderDate(new Date());
							inWo.setOriginBizNo(feedPlanNotice.getNoticeNo());//取送货计划的单号
							inWo.setWhCode(feedPlanNotice.getWhCode());
							inWo.setWoType(feedPlanNotice.getPickingType());
							inWo.setOriginNoticeNo(feedPlanNotice.getNoticeNo());//关联noticeno字段
							//inWo.setExecuteTime(new Date());
							//inWo.setExecutor("8888");//自动化助手，默认指定用户
							JpaUtil.save(inWo);
						}
						WarehouseOrderLine line = new WarehouseOrderLine();
						line.setWhCode(inWo.getWhCode());
						line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
						line.setItemCode(vo.getItemCode());
						Item item = itemMap.get(vo.getItemCode());
						if (item!=null){
							line.setItemGroupCode(item.getItemGroupCode());
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
						}
						line.setQuantity(vo.getQuantity());
						line.setBizNo(inWo.getBizNo());
						line.setLineNo(lineNo+"");
						line.setOriginBizNo(feedPlanNotice.getNoticeNo());//取送货计划的单号
						line.setOriginBizLineNo(vo.getNoticeLineNo());//取送货计划的行号
						line.setSort(vo.getSort());
						//通知单执行，均为入的情况
						if(context.getLotService() == null){
							line.setLotNo("none");
							line.setSubLotIndex("0");
						}else{
							Lot newLot = context.getLotService().getNewLot(feedPlanNotice, vo, typesMap);
							if (newLot!=null){
								line.setLotNo(newLot.getLotNo());
								line.setSubLotIndex(newLot.getSubLotIndex());
							}else{
								line.setLotNo("none");
								line.setSubLotIndex("0");
							}
						}
						line.setOriginNoticeNo(feedPlanNotice.getNoticeNo());
						line.setOriginNoticeLineNo(vo.getNoticeLineNo());
						JpaUtil.save(line);
						inWoLines.add(line);
					}

					//确认对应的领(补)料通知单，且生成对应的出库仓单，且仓单自动执行。执行的明细和入对应(批次)
					String sourcePickingNoticeNo = feedPlanNotice.getSourcePickingNoticeNo();//源领/补料通知单
					MoPickingNotice pickingNotice = JpaUtil.linq(MoPickingNotice.class).collect("noticeNo", MoPickingNoticeLine.class, "noticeNo").equal("noticeNo", sourcePickingNoticeNo).findOne();
					pickingNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());//确认状态
					pickingNotice.setSaveTransient(true);//保存子表
					List<MoPickingNoticeLine> moPickingNoticeLines = pickingNotice.getMoPickingNoticeLines();
					Map<String, MoPickingNoticeLine> pickingNoticeLineMap = JpaUtil.index(moPickingNoticeLines, "lineNo");
					List<FeedPlanNoticeLine> feedPlanNoticeLines = JpaUtil.linq(FeedPlanNoticeLine.class).equal("noticeNo", feedPlanNotice.getNoticeNo()).list();
					Map<String, FeedPlanNoticeLine> feedPlanNoticeLineMap = JpaUtil.index(feedPlanNoticeLines, "sourcePickingNoticeLineNo");

					Map<Object, WarehouseOrderLine> warehouseOrderLineMap = JpaUtil.index(inWoLines, "originNoticeLineNo");

					List<OrderExcuteLineVo> woVos = new ArrayList<>();
					for (String mpLineNo:pickingNoticeLineMap.keySet()){
						MoPickingNoticeLine moPickingNoticeLine = pickingNoticeLineMap.get(mpLineNo);
						FeedPlanNoticeLine feedPlanNoticeLine = feedPlanNoticeLineMap.get(mpLineNo);
						WarehouseOrderLine warehouseOrderLine = warehouseOrderLineMap.get(feedPlanNoticeLine.getLineNo());
						moPickingNoticeLine.setQuantity(warehouseOrderLine.getQuantity());//确认数量
						moPickingNoticeLine.setLotNo(warehouseOrderLine.getLotNo());
						moPickingNoticeLine.setSubLotIndex(warehouseOrderLine.getSubLotIndex());
						moPickingNoticeLine.setCrudType(CrudType.UPDATE);

						OrderExcuteLineVo excuteLineVo = new OrderExcuteLineVo();
						excuteLineVo.setBizOrderNo(moPickingNoticeLine.getOriginBizNo());
						excuteLineVo.setBizOrderlineNo(moPickingNoticeLine.getOriginBizLineNo());
						excuteLineVo.setItemCode(moPickingNoticeLine.getItemCode());
						excuteLineVo.setLineQuantity(moPickingNoticeLine.getQuantity());
						excuteLineVo.setLotNo(moPickingNoticeLine.getLotNo());
						excuteLineVo.setSubLotIndex(moPickingNoticeLine.getSubLotIndex());
						excuteLineVo.setQuantity(moPickingNoticeLine.getQuantity());
						excuteLineVo.setWhCode(pickingNotice.getWhCode());
						excuteLineVo.setMemo(moPickingNoticeLine.getMemo());
						excuteLineVo.setNoticeNo(pickingNotice.getNoticeNo());
						excuteLineVo.setNoticeLineNo(moPickingNoticeLine.getLineNo());
						woVos.add(excuteLineVo);
					}
					JpaUtil.save(pickingNotice);//保存 领料通知，主从数据

					//生成未执行的出库仓单
					WarehouseOrder outWo = null;
					int woLineNo = 0;
					for(OrderExcuteLineVo vo : woVos){
						woLineNo++;
						if(outWo == null){
							outWo = new WarehouseOrder();
							outWo.setAccessType(pickingNotice.getAccessType());
							outWo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
							outWo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
							outWo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
							outWo.setOrderDate(new Date());
							outWo.setOriginBizNo(vo.getBizOrderNo());
							outWo.setWhCode(vo.getWhCode());
							outWo.setWoType(pickingNotice.getPickingType());
							outWo.setOriginNoticeNo(pickingNotice.getNoticeNo());//关联noticeno字段
							JpaUtil.save(outWo);
						}
						WarehouseOrderLine line = new WarehouseOrderLine();
						line.setWhCode(outWo.getWhCode());
						line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
						Item item = itemMap.get(vo.getItemCode());
						line.setItemCode(vo.getItemCode());
						if (item!=null){
							line.setItemGroupCode(item.getItemGroupCode());
							line.setItemName(item.getItemName());
							line.setItemSpec(item.getItemSpec());
							line.setUnitCode(item.getUnitCode());
							line.setDrawingNo(item.getDrawingNo());
						}
						line.setQuantity(vo.getQuantity());
						line.setBizNo(outWo.getBizNo());
						line.setLineNo(woLineNo+"");
						line.setOriginBizNo(vo.getBizOrderNo());
						line.setOriginBizLineNo(vo.getBizOrderlineNo());
						line.setSort(woLineNo+"");
						line.setLotNo(vo.getLotNo());
						line.setSubLotIndex(vo.getSubLotIndex());
						line.setOriginNoticeNo(vo.getNoticeNo());
						line.setOriginNoticeLineNo(vo.getNoticeLineNo());
						JpaUtil.save(line);
					}

				}
			}
			afterExecute(context);
			feedPlanNotice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());
			JpaUtil.update(feedPlanNotice);
		} else {
			if(CollectionUtils.isEmpty(context.getErrors())) {
				context.addError("前置校验不通过");
			}
		}

	}

	@Override
	public NoticeContext config(NoticeContext context) {
		context.setOrderExcuteVos(orderExcuteVos);
		return context;
	}

	@Override
	public boolean beforeExecute(NoticeContext context) {
		return true;
	}

	@Override
	public void afterExecute(NoticeContext context) {
		
	}

}
